﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Schema;
using System.Reflection;
using System.Xml;
using System.IO;

namespace ServerSide.Model
{
    /// <summary>
    /// Xml validator
    /// </summary>
    public class XmlValidator
    {
        /// <summary>
        /// Instance of XML validator
        /// </summary>
        private static XmlValidator instance;

        /// <summary>
        /// Get the instance of XML validator
        /// </summary>
        public static XmlValidator Instance
        {
            get
            {
                if (instance == null)
                    instance = new XmlValidator();
                return instance;
            }
        }

        /// <summary>
        /// Create XMLSchema from xsd file
        /// </summary>
        /// <param name="xsdName">The name of xsd file which is stored in resources</param>
        /// <returns>XmlSchema</returns>
        /// <remarks></remarks>
        public XmlSchema CreateSchema(string xsdName)
        {
            XmlSchema schema = null;
            try
            {
                var execAssembly = Assembly.GetExecutingAssembly();
                var execNamespace = execAssembly.GetName().Name.ToString();

                // Read xsd schema file from resource
                using (Stream myStream = execAssembly.GetManifestResourceStream(execNamespace + ".Data." + xsdName))
                {
                    schema = XmlSchema.Read(myStream, null);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Errors in XML validation: {0}", ex.Message));
            }
            return schema;
        }

        /// <summary>
        /// Method for XML validation
        /// </summary>
        /// <param name="xmlFile">XML file to validate</param>
        /// <param name="schema">XSD schema</param>
        /// <remarks></remarks>
        public void ValidateXML(string xmlFile, XmlSchema schema)
        {
            try
            {
                // Set setting for xml validation
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.ValidationType = ValidationType.Schema;
                settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema;
                settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ProcessSchemaLocation;
                settings.Schemas.Add(schema);

                // Add handler for errors
                settings.ValidationEventHandler += XMLValidationHandler;

                // Create the schema validating reader
                using (XmlReader reader = XmlReader.Create(xmlFile, settings))
                {
                    while (reader.Read()) { }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Errors in XML validation: {0}", ex.Message));
            }
        }

        /// <summary>
        /// Handling errors for XML validation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void XMLValidationHandler(object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Error)
            {
                throw new Exception(string.Format("Xml content is invalid: {0}", e.Message));
            }
        }
    }
}
